package com.htudata.live.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;

import com.htudata.alarm.pojo.po.AlarmLevelPO;
import com.htudata.alarm.service.AlarmLevelService;
import com.htudata.alarm.service.AlarmShowService;
import com.htudata.core.util.operation.FastJsonOperationUtils;
import com.htudata.core.util.operation.ListPagingOperationUtils;
import com.htudata.live.dao.LiveDao;
import com.htudata.live.service.VirtualStationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class VirtualStationServiceImpl implements VirtualStationService {

  @Autowired
  private LiveDao liveDao;
  
  @Autowired
  private AlarmShowService alarmShowService;
  
  @Autowired
  private AlarmLevelService alarmLevelService;
  
  @Autowired
  private HttpServletRequest request;
  
  @Value("${virtual_station}")
  private int VIRTUALSTATION;
  
  @Value("${recover_time_range}")
  private int recover_time_range;
  
  @Value("${prov}")
  private String prov;
  
  public JSONObject getVirtualStationList(String nodeId, String provCode, String areaCode, int level, int pageNum, int pageSize) {
    JSONObject result = new JSONObject(true);
    List<JSONObject> virtualStationList = new ArrayList<>();
    int total = 0;
    List<Long> userIds = null;
    int timestamp = (int)(System.currentTimeMillis() / 1000L);
    int recoverTime = timestamp - this.recover_time_range;
    List<AlarmLevelPO> alarmLevelList = this.alarmLevelService.getAlarmLevelList("");
    if (level == -2) {
      JSONArray virtualStations = this.liveDao.selectVirtualStationList(this.VIRTUALSTATION, nodeId, areaCode, level, userIds);
      JSONArray alarmCountJSONArray = this.alarmShowService.getNodeAlarmCountByVirtualStation(recoverTime, this.VIRTUALSTATION, nodeId, areaCode);
      JSONObject alarmCountJSONObject = FastJsonOperationUtils.JSONArrayToJSONObejct(alarmCountJSONArray, "node_id", false);
      virtualStations.forEach(virtualStationObject -> {
            JSONObject virtualStation = (JSONObject)virtualStationObject;
            handleVirtualStationAlarm(virtualStation, alarmCountJSONObject, alarmLevelList);
          });
      virtualStationList = virtualStations.toJavaList(JSONObject.class);
      total = virtualStationList.size();
      if (pageNum != 0 && pageSize != 0 && 
        virtualStationList.size() > 0) {
        ListPagingOperationUtils<JSONObject> listPageUtil = new ListPagingOperationUtils(virtualStationList, pageNum, pageSize);
        virtualStationList = listPageUtil.getPagedList();
      } 
    } else if (level == -1) {
      JSONArray virtualStations = this.liveDao.selectVirtualStationList(this.VIRTUALSTATION, nodeId, areaCode, level, userIds);
      JSONArray alarmCountJSONArray = this.alarmShowService.getNodeAlarmCountByVirtualStation(recoverTime, this.VIRTUALSTATION, nodeId, areaCode);
      JSONObject alarmCountJSONObject = FastJsonOperationUtils.JSONArrayToJSONObejct(alarmCountJSONArray, "node_id", false);
      virtualStations.forEach(virtualStationObject -> {
            JSONObject virtualStation = (JSONObject)virtualStationObject;
            handleVirtualStationAlarm(virtualStation, alarmCountJSONObject, alarmLevelList);
          });
      virtualStationList = virtualStations.toJavaList(JSONObject.class);
      total = virtualStationList.size();
      virtualStationList = (List<JSONObject>)virtualStationList.stream().filter(virtualStation -> (virtualStation.getIntValue("level") == -1)).collect(Collectors.toList());
      if (pageNum != 0 && pageSize != 0 && 
        virtualStationList.size() > 0) {
        ListPagingOperationUtils<JSONObject> listPageUtil = new ListPagingOperationUtils(virtualStationList, pageNum, pageSize);
        virtualStationList = listPageUtil.getPagedList();
      } 
    } else {
      JSONArray alarmCountJSONArray = this.alarmShowService.getNodeAlarmCountByLevel(recoverTime, this.VIRTUALSTATION, nodeId, areaCode, level);
      JSONArray virtualStations = handleVirtualStationAlarm2(alarmCountJSONArray, alarmLevelList);
      virtualStationList = virtualStations.toJavaList(JSONObject.class);
      total = virtualStationList.size();
      if (pageNum != 0 && pageSize != 0 && 
        virtualStationList.size() > 0) {
        ListPagingOperationUtils<JSONObject> listPageUtil = new ListPagingOperationUtils(virtualStationList, pageNum, pageSize);
        virtualStationList = listPageUtil.getPagedList();
      } 
    } 
    result.put("virtualStations", virtualStationList);
    result.put("total", Integer.valueOf(total));
    return result;
  }
  
  public void handleVirtualStationAlarm(JSONObject virtualStation, JSONObject problemCountJSONObject, JSONObject alarmCountJSONObject, List<AlarmLevelPO> alarmLevelList) {
    String nodeId = virtualStation.getString("nodeId");
    JSONObject problemCount = null;
    JSONObject alarmCount = null;
    if (problemCountJSONObject.containsKey(nodeId) && alarmCountJSONObject.containsKey(nodeId)) {
      problemCount = (JSONObject)problemCountJSONObject.get(nodeId);
      alarmCount = (JSONObject)alarmCountJSONObject.get(nodeId);
      problemCount = getNewProblemCount(problemCount, alarmCount);
    } else if (problemCountJSONObject.containsKey(nodeId)) {
      problemCount = (JSONObject)problemCountJSONObject.get(nodeId);
    } else if (alarmCountJSONObject.containsKey(nodeId)) {
      problemCount = (JSONObject)alarmCountJSONObject.get(nodeId);
    } else {
      problemCount = null;
      alarmCount = null;
    } 
    if (!Objects.isNull(problemCount)) {
      AlarmLevelPO alarmLevelPO = AlarmLevelService.getAlarmLevelInfo(alarmLevelList, problemCount
          .getIntValue("level"));
      virtualStation.put("level", Integer.valueOf(alarmLevelPO.getLevel()));
      virtualStation.put("color", alarmLevelPO.getColor());
      virtualStation.put("problemCount", Integer.valueOf(problemCount.getIntValue("problemCount")));
    } else {
      virtualStation.put("level", Integer.valueOf(-1));
      virtualStation.put("color", "");
      virtualStation.put("problemCount", Integer.valueOf(0));
    } 
  }
  
  public void handleVirtualStationAlarm(JSONObject virtualStation, JSONObject alarmCountJSONObject, List<AlarmLevelPO> alarmLevelList) {
    String nodeId = virtualStation.getString("nodeId");
    JSONObject problemCount = (JSONObject)alarmCountJSONObject.get(nodeId);
    if (!Objects.isNull(problemCount)) {
      AlarmLevelPO alarmLevelPO = AlarmLevelService.getAlarmLevelInfo(alarmLevelList, problemCount
          .getIntValue("level"));
      virtualStation.put("level", Integer.valueOf(alarmLevelPO.getLevel()));
      virtualStation.put("color", alarmLevelPO.getColor());
      virtualStation.put("problemCount", Integer.valueOf(problemCount.getIntValue("problemCount")));
    } else {
      virtualStation.put("level", Integer.valueOf(-1));
      virtualStation.put("color", "");
      virtualStation.put("problemCount", Integer.valueOf(0));
    } 
  }
  
  public JSONArray handleVirtualStationAlarm2(JSONArray problemCountJSONArray, JSONArray alarmCountJSONArray, List<AlarmLevelPO> alarmLevelList) {
    JSONArray virtualStationList = new JSONArray();
    Map<String, JSONObject> virtualStationMap = new HashMap<>();
    problemCountJSONArray.forEach(problemCount -> {
          JSONObject problemCountObject = (JSONObject)problemCount;
          virtualStationMap.put(problemCountObject.getString("nodeId"), problemCountObject);
        });
    alarmCountJSONArray.forEach(alarmCount -> {
          JSONObject alarmCountObject = (JSONObject)alarmCount;
          String nodeId = alarmCountObject.getString("nodeId");
          if (virtualStationMap.containsKey(nodeId)) {
            JSONObject problemCountObject = (JSONObject)virtualStationMap.get(nodeId);
            if (alarmCountObject.getIntValue("level") == alarmCountObject.getIntValue("level")) {
              problemCountObject.put("problemCount", Integer.valueOf(problemCountObject.getIntValue("problemCount") + alarmCountObject.getIntValue("problemCount")));
            } else if (alarmCountObject.getIntValue("level") > alarmCountObject.getIntValue("level")) {
              virtualStationMap.put(nodeId, alarmCountObject);
            } 
          } else {
            virtualStationMap.put(alarmCountObject.getString("nodeId"), alarmCountObject);
          } 
        });
    for (Map.Entry<String, JSONObject> entry : virtualStationMap.entrySet()) {
      JSONObject virtualStation = (JSONObject)entry.getValue();
      AlarmLevelPO alarmLevelPO = AlarmLevelService.getAlarmLevelInfo(alarmLevelList, virtualStation
          .getIntValue("level"));
      virtualStation.put("color", alarmLevelPO.getColor());
      virtualStationList.add(virtualStation);
    } 
    return virtualStationList;
  }
  
  public JSONArray handleVirtualStationAlarm2(JSONArray alarmCountJSONArray, List<AlarmLevelPO> alarmLevelList) {
    JSONArray virtualStationList = new JSONArray();
    Map<String, JSONObject> virtualStationMap = new HashMap<>();
    alarmCountJSONArray.forEach(alarmCount -> {
          JSONObject alarmCountObject = (JSONObject)alarmCount;
          String nodeId = alarmCountObject.getString("nodeId");
          if (virtualStationMap.containsKey(nodeId)) {
            JSONObject problemCountObject = (JSONObject)virtualStationMap.get(nodeId);
            if (alarmCountObject.getIntValue("level") == alarmCountObject.getIntValue("level")) {
              problemCountObject.put("problemCount", Integer.valueOf(problemCountObject.getIntValue("problemCount") + alarmCountObject.getIntValue("problemCount")));
            } else if (alarmCountObject.getIntValue("level") > alarmCountObject.getIntValue("level")) {
              virtualStationMap.put(nodeId, alarmCountObject);
            } 
          } else {
            virtualStationMap.put(alarmCountObject.getString("nodeId"), alarmCountObject);
          } 
        });
    for (Map.Entry<String, JSONObject> entry : virtualStationMap.entrySet()) {
      JSONObject virtualStation = (JSONObject)entry.getValue();
      AlarmLevelPO alarmLevelPO = AlarmLevelService.getAlarmLevelInfo(alarmLevelList, virtualStation
          .getIntValue("level"));
      virtualStation.put("color", alarmLevelPO.getColor());
      virtualStationList.add(virtualStation);
    } 
    return virtualStationList;
  }
  
  private JSONObject getNewProblemCount(JSONObject problemCount, JSONObject alarmCount) {
    JSONObject result = new JSONObject();
    int level1 = problemCount.getIntValue("level");
    int level2 = alarmCount.getIntValue("level");
    if (level1 == level2) {
      result.put("level", Integer.valueOf(level1));
      result.put("problemCount", Integer.valueOf(Integer.parseInt(problemCount.getOrDefault("problemCount", "0") + "") + 
            Integer.parseInt(alarmCount.getOrDefault("problemCount", "0") + "")));
    } else if (level1 > level2) {
      result.put("level", Integer.valueOf(level1));
      result.put("problemCount", Integer.valueOf(Integer.parseInt(problemCount.getOrDefault("problemCount", "0") + "")));
    } else {
      result.put("level", Integer.valueOf(level2));
      result.put("problemCount", Integer.valueOf(Integer.parseInt(alarmCount.getOrDefault("problemCount", "0") + "")));
    } 
    return result;
  }
  
  public JSONArray getStatisVirtualStation(String nodeId, String areaCode, int level) {
    List<Long> userIds = null;
    JSONArray result = this.liveDao.getStatisVirtualStation(this.VIRTUALSTATION, nodeId, areaCode, level, userIds, this.prov);
    result.forEach(obj -> {
          JSONObject temp = (JSONObject)obj;
          if (level == -2) {
            temp.put("count", Integer.valueOf(temp.getIntValue("allTotal")));
          } else if (level == -1) {
            temp.put("count", Integer.valueOf(temp.getIntValue("allTotal") - temp.getIntValue("errorTotal")));
          } else {
            temp.put("count", Integer.valueOf(temp.getIntValue("errorTotal")));
          } 
        });
    return result;
  }
}
